package com.aispeech.asr.comm.etcd;

import com.aispeech.asr.comm.utils.HttpUtils;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.apache.commons.lang3.StringUtils;

import java.util.Properties;

public class EtcdConfigClient {
    public static Properties loadEtcdConfig(String etcdServerLists) throws JsonProcessingException {
        String leader = getEtcdLeader(etcdServerLists);
        return StringUtils.isBlank(leader) ? null : loadConfigfFromLeader(leader);
    }

    private static Properties loadConfigfFromLeader(String leader) throws JsonProcessingException {
        String projectIndentification = System.getenv("ETCD_PROJECT_IDENTIFICATION");

        Properties properties;
        if (StringUtils.isNoneBlank(projectIndentification)) {
            System.out.println(String.format(
                    "[ EtcdEnvironmentPostProcessor ] Load configuration from ETCD server: %s, path: %s ...",
                    leader,
                    projectIndentification
            ));

            String message = HttpUtils.get(String.format("%s/v2/keys/%s?recursive=true&sorted=true",
                    leader, projectIndentification));

            properties = parseEtcdConfig(projectIndentification, message);
        } else {
            throw new RuntimeException("No project identification is configured in Dockerfile.");
        }

        return properties;
    }

    private static Properties parseEtcdConfig(String indentification, String message) throws JsonProcessingException {
        Properties properties = null;
        int index = indentification.length();


        if (StringUtils.isNoneBlank(message)) {
            ObjectMapper objectMapper = new ObjectMapper();
            JsonNode json = objectMapper.readTree(message);
            JsonNode jsonNodes = json.get("node").get("nodes");

            if (jsonNodes != null && jsonNodes.size() > 0) {
                properties = new Properties();

                String hostname = System.getenv("HOSTNAME");
                boolean isGrayNode = (StringUtils.isNoneBlank(hostname) && hostname.contains("-instance"));
                JsonNode itemGray = null;

                for (int i = 0; i < jsonNodes.size(); i++) {
                    JsonNode item = jsonNodes.get(i);

                    if (item != null) {
                        String key = item.get("key").asText().substring(index + 2);


                        if (item.get("dir") != null && "gray".equalsIgnoreCase(key)) {
                            itemGray = item;
                        } else {

                            JsonNode jv = item.get("value");

                            if (jv != null) {
                                properties.setProperty(key, jv.asText());
                            } else {

                                System.out.println(String.format(
                                        "[ parseEtcdConfig ] key: %s, value: %s",
                                        key,
                                        jv
                                ));
                            }
                        }
                    }
                }

                if (isGrayNode && itemGray != null) {
                    jsonNodes = itemGray.get("nodes");

                    for (int i = 0; i < jsonNodes.size(); i++) {
                        JsonNode item = jsonNodes.get(i);

                        if (item != null) {
                            String key = item.get("key").asText().substring(index + 7);
                            JsonNode jv = item.get("value");

                            if (jv != null) {
                                properties.setProperty(key, jv.asText());
                            }
                        }
                    }
                }
            }
        }

        return properties;
    }

    private static String getEtcdLeader(String etcdServerLists) throws JsonProcessingException {
        String filted = etcdServerLists
                .replace("\"", "")
                .replace("'", "")
                .replace("[", "")
                .replace("]", "");

        if (StringUtils.isNoneBlank(filted)) {
            String[] arrServerList = filted.split(",");

            for (int i = 0; i < arrServerList.length; i++) {
                String node = arrServerList[i];
                try {
                    String result = HttpUtils.get(node + "/v2/stats/leader");

                    if (isMaster(result))
                        return node;
                } catch (RuntimeException ex) { }
            }
        }

        return null;
    }

    private static boolean isMaster(String result) {
        ObjectMapper mapper = new ObjectMapper();
        String leader = null;
        JsonNode node;

        try {
            node = mapper.readTree(result);
            leader = node.get("leader").asText();
        } catch (Exception ex) {
            System.out.println(String.format("[ isMaster ] Unknown response: %s ...", result));
        }

        return StringUtils.isNoneBlank(leader);
    }
}
